#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Collections.Generic;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.GamerServices;
using System.IO.IsolatedStorage;
#endregion

namespace UglyAnimals
{
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    class GameplayScreen : GameScreen
    {
        #region Fields

        enum PlayerState
        {
            TensingSlingshot,
            ShootingAway,
            Flying,
            Sliding
        };


        ContentManager content;
        SpriteFont gameFont;

        #region player members
        // Represents the player 
        Player player;
        PlayerState playerState;
        Vector2 playerPosition;
        Vector2 playerStartPosition;
        Vector2 shootingPlayerVector;

        #endregion

        bool isGameOverDialogShown = false;
        bool isScreenTouched;
        bool isTensing;
        int score;
        Obstacle lastFlyingObstacle;
        int jumpingCount;

        float gravityMultiplicator;

        // Image used to display the static background
        Texture2D mainBackground;

        // Parallaxing Layers
        ParallaxingBackground bgLayer1;
        ParallaxingBackground bgLayer2;

        private int groundHeight;

        // obstacle textures
        Texture2D[] obstacleTextures = new Texture2D[4];
        List<Obstacle> obstacles;
        private int groundObstacles;
        private int flyingObstacles;
        private int helperObstacles;

        Explosion explosion;

        Slingshot slingshot;


        // Sound
        Song backgroundMusic;
        SoundEffect jumpSound;
        SoundEffect explosionSound;

        private bool isSoundEnabled;
        private bool collidedWithHelperObstacle;
        private bool isJumping;
        private bool isMusicEnabled;

        Random random = new Random();

        #endregion

        #region Initialization


        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen()
        {
            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);

            bgLayer1 = new ParallaxingBackground();
            bgLayer2 = new ParallaxingBackground();
            groundHeight = 34;
            isSoundEnabled = StorageManager.GetInstance().IsSoundEnabled;
            isMusicEnabled = StorageManager.GetInstance().IsMusicEnabled;

            player = new Player();
            playerState = PlayerState.TensingSlingshot;
            isScreenTouched = false;
            isTensing = false;
            gravityMultiplicator = 1.5f;
            score = 0;
            jumpingCount = 0;
            groundObstacles = 0;
            flyingObstacles = 0;
            helperObstacles = 0;

        }


        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            gameFont = content.Load<SpriteFont>("gamefont");

            playerStartPosition = new Vector2(ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.X + ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Width / 5, ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Y
            + ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Height / 3 * 2);

            List<Animal> animals = new List<Animal>();

            #region load naked mole
            Texture2D nakedMoleStanding = content.Load<Texture2D>("nakedmoleStanding");
            Texture2D nakedMoleStarting = content.Load<Texture2D>("nakedmoleStarting");
            Texture2D nakedMoleFlying = content.Load<Texture2D>("nakedmoleFlying");
            Texture2D nakedMoleLanding = content.Load<Texture2D>("nakedmoleLanding");
            Texture2D nakedMoleSliding = content.Load<Texture2D>("nakedmoleSliding");
            List<Animation> nakedMoleAnimations = new List<Animation>();

            Animation nakedMoleStandingAnimation = new Animation();
            nakedMoleStandingAnimation.Initialize(nakedMoleStanding, Vector2.Zero, 50, 40, 1, 30, Color.White, 1.2f, false, true);
            nakedMoleAnimations.Add(nakedMoleStandingAnimation);

            Animation nakedMoleStartingAnimation = new Animation();
            nakedMoleStartingAnimation.Initialize(nakedMoleStarting, Vector2.Zero, 55, 50, 4, 70, Color.White, 1.2f, false, true);
            nakedMoleAnimations.Add(nakedMoleStartingAnimation);

            Animation nakedMoleFlyingAnimation = new Animation();
            nakedMoleFlyingAnimation.Initialize(nakedMoleFlying, Vector2.Zero, 55, 50, 1, 30, Color.White, 1.2f, false, true);
            nakedMoleAnimations.Add(nakedMoleFlyingAnimation);

            Animation nakedMoleLandingAnimation = new Animation();
            nakedMoleLandingAnimation.Initialize(nakedMoleLanding, Vector2.Zero, 60, 50, 3, 30, Color.White, 1.2f, false, true);
            nakedMoleAnimations.Add(nakedMoleLandingAnimation);

            Animation nakedMoleSlidingAnimation = new Animation();
            nakedMoleSlidingAnimation.Initialize(nakedMoleSliding, Vector2.Zero, 50, 40, 1, 30, Color.White, 1.2f, false, true);
            nakedMoleAnimations.Add(nakedMoleLandingAnimation);
            Animal nakedMole = new Animal();
            nakedMole.Initialize(nakedMoleAnimations, playerStartPosition, 2.5f, 1f, 3f, 2f);
            animals.Add(nakedMole);
            #endregion

            #region load seacow
            Texture2D seacowStanding = content.Load<Texture2D>("seacowStanding");
            Texture2D seacowStarting = content.Load<Texture2D>("seacowStarting");
            Texture2D seacowFlying = content.Load<Texture2D>("seacowFlying");
            Texture2D seacowLanding = content.Load<Texture2D>("seacowLanding");
            Texture2D seacowSliding = content.Load<Texture2D>("seacowSliding");
            List<Animation> seacowAnimations = new List<Animation>();


            Animation seacowStandingAnimation = new Animation();
            seacowStandingAnimation.Initialize(seacowStanding, Vector2.Zero, 30, 35, 1, 30, Color.White, 2f, false, true);
            seacowAnimations.Add(seacowStandingAnimation);

            Animation seacowStartingAnimation = new Animation();
            seacowStartingAnimation.Initialize(seacowStarting, Vector2.Zero, 30, 35, 2, 70, Color.White, 2f, true, false);
            seacowAnimations.Add(seacowStartingAnimation);

            Animation seacowFlyingAnimation = new Animation();
            seacowFlyingAnimation.Initialize(seacowFlying, Vector2.Zero, 30, 35, 1, 30, Color.White, 2f, false, true);
            seacowAnimations.Add(seacowFlyingAnimation);

            Animation seacowLandingAnimation = new Animation();
            seacowLandingAnimation.Initialize(seacowLanding, Vector2.Zero, 35, 35, 2, 40, Color.White, 2f, false, true);
            seacowAnimations.Add(seacowLandingAnimation);

            Animation seacowSlidingAnimation = new Animation();
            seacowSlidingAnimation.Initialize(seacowSliding, Vector2.Zero, 40, 35, 1, 30, Color.White, 2f, false, true);
            seacowAnimations.Add(seacowSlidingAnimation);

            Animal seacow = new Animal();
            seacow.Initialize(seacowAnimations, playerStartPosition, 3.5f, 0.7f, 1f, 2f);

            animals.Add(seacow);
            #endregion

            #region load turkey
            Texture2D turkeyStanding = content.Load<Texture2D>("turkeyStanding");
            Texture2D turkeyStarting = content.Load<Texture2D>("turkeyStarting");
            Texture2D turkeyFlying = content.Load<Texture2D>("turkeyFlying");
            Texture2D turkeyLanding = content.Load<Texture2D>("turkeyLanding");
            Texture2D turkeySliding = content.Load<Texture2D>("turkeySliding");
            List<Animation> turkeyAnimations = new List<Animation>();


            Animation turkeyStandingAnimation = new Animation();
            turkeyStandingAnimation.Initialize(turkeyStanding, Vector2.Zero, 40, 50, 1, 30, Color.White, 1.2f, false, true);
            turkeyAnimations.Add(turkeyStandingAnimation);

            Animation turkeyStartingAnimation = new Animation();
            turkeyStartingAnimation.Initialize(turkeyStarting, Vector2.Zero, 40, 50, 2, 70, Color.White, 1.2f, false, true);
            turkeyAnimations.Add(turkeyStartingAnimation);

            Animation turkeyFlyingAnimation = new Animation();
            turkeyFlyingAnimation.Initialize(turkeyFlying, Vector2.Zero, 40, 70, 4, 30, Color.White, 1.2f, true, false);
            turkeyAnimations.Add(turkeyFlyingAnimation);

            Animation turkeyLandingAnimation = new Animation();
            turkeyLandingAnimation.Initialize(turkeyLanding, Vector2.Zero, 40, 70, 2, 30, Color.White, 1.2f, false, true);
            turkeyAnimations.Add(turkeyLandingAnimation);

            Animation turkeySlidingAnimation = new Animation();
            turkeySlidingAnimation.Initialize(turkeySliding, Vector2.Zero, 42, 40, 1, 30, Color.White, 1.2f, false, true);
            turkeyAnimations.Add(turkeySlidingAnimation);

            Animal turkey = new Animal();
            turkey.Initialize(turkeyAnimations, playerStartPosition, 1.8f, 0.9f, 2f, 10f);

            animals.Add(turkey);
            #endregion


            playerPosition = playerStartPosition;

            player.Initialize(animals);
            player.PlayerAnimal = animals[StorageManager.GetInstance().SelectedAnimal];

            // Load the parallaxing background
            bgLayer1.Initialize(content, "layer2", ScreenManager.GraphicsDevice.Viewport.Width);
            bgLayer2.Initialize(content, "layer3", ScreenManager.GraphicsDevice.Viewport.Width);

            mainBackground = content.Load<Texture2D>("layer1");

            // play background music when sound is enabled
            if (isMusicEnabled)
            {
                backgroundMusic = content.Load<Song>("sound/smb");
                PlayMusic(backgroundMusic);
            }

            if (isSoundEnabled)
            {
                jumpSound = content.Load<SoundEffect>("sound/jump");
                explosionSound = content.Load<SoundEffect>("sound/explosion");
            }

            // load Obstacle textures
            obstacleTextures[(int)Obstacle.ObstacleType.Stones] = content.Load<Texture2D>("stones");
            obstacleTextures[(int)Obstacle.ObstacleType.Ice] = content.Load<Texture2D>("ice");
            obstacleTextures[(int)Obstacle.ObstacleType.Ballon] = content.Load<Texture2D>("mineAnimation");
            obstacleTextures[(int)Obstacle.ObstacleType.Trampoline] = content.Load<Texture2D>("trampoline");
            obstacles = new List<Obstacle>();

            // load the slinghsot content
            Texture2D slingshotFrontTexture = content.Load<Texture2D>("slingshotFront");
            Texture2D slingshotBackTexture = content.Load<Texture2D>("slingshotBack");
            slingshot = new Slingshot();
            slingshot.Initialize(new Vector2(playerStartPosition.X - slingshotFrontTexture.Width / 12 * 10, playerStartPosition.Y - slingshotFrontTexture.Height / 10 * 2), slingshotFrontTexture, slingshotBackTexture, playerPosition);

            // load the explosion content
            Texture2D explosionTexture = content.Load<Texture2D>("explosion");
            Animation explosionAnimation = new Animation();
            explosionAnimation.Initialize(explosionTexture, new Vector2(ScreenManager.GraphicsDevice.Viewport.Width + 100, 0), 134, 134, 12, 40, Color.White, 1f, false, false);
            explosion = new Explosion();
            explosion.Initialize(explosionAnimation, new Vector2(ScreenManager.GraphicsDevice.Viewport.Width + 100, 0));

            // once the load has finished, we use ResetElapsedTime to tell the game's
            // timing mechanism that we have just finished a very long frame, and that
            // it should not try to catch up.
            ScreenManager.Game.ResetElapsedTime();
        }


        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        public override void UnloadContent()
        {
            content.Unload();
        }


        #endregion

        #region Update and Draw


        /// <summary>
        /// Updates the state of the game. This method checks the GameScreen.IsActive
        /// property, so the game will stop updating when the pause menu is active,
        /// or if you tab away to a different application.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {
            if (IsActive)
            {
                UpdatePlayer(gameTime);
                UpdateBackground();

                // update obstacles
                UpdateObstacles(gameTime);

                // update slinghot
                UpdateSlingshot(gameTime);
                UpdateExplosion(gameTime);

                // update collision
                checkForCollision();

                jumpingCount++;
                UpdateScore();
            }
            if (!player.Active && !explosion.Active && !isGameOverDialogShown)
            {
                isGameOverDialogShown = true;
                List<string> MBOPTIONS = new List<string>();
                MBOPTIONS.Add("Save");
                MBOPTIONS.Add("Cancel");
                string msg = "Your Score: " + score + "\n\nSave to highscore list?";
                Guide.BeginShowMessageBox("GAME OVER",
                    msg,
                    MBOPTIONS,
                    0,
                    MessageBoxIcon.Alert,
                    GetUserChoice,
                    null);
            }

            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
        }

        protected void GetUserChoice(IAsyncResult r)
        {
            int? b = Guide.EndShowMessageBox(r);

            if (b == 0)
            {
                // save pressed
                // store high score
                if (score > 0)
                {
                    StorageManager sm = StorageManager.GetInstance();
                    string pname = sm.PlayerName;
                    sm.AddHighScore(pname, score);
                }
            }
            MediaPlayer.Stop();
            LoadingScreen.Load(ScreenManager, false, ControllingPlayer, new BackgroundScreen(), new MainMenuScreen());
        }

        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(InputState input)
        {
            if (input == null)
                throw new ArgumentNullException("input");

            // Look up inputs for the active player profile.
            int playerIndex = (int)ControllingPlayer.Value;

            KeyboardState keyboardState = input.CurrentKeyboardStates[playerIndex];
            GamePadState gamePadState = input.CurrentGamePadStates[playerIndex];

            // if the user pressed the back button, we return to the main menu
            PlayerIndex playerIdx;
            if (input.IsNewButtonPress(Buttons.Back, ControllingPlayer, out playerIdx))
            {
                MediaPlayer.Stop();
                LoadingScreen.Load(ScreenManager, false, ControllingPlayer, new BackgroundScreen(), new MainMenuScreen());
            }

            if (playerState == PlayerState.TensingSlingshot)
            {
                foreach (TouchLocation tl in input.TouchState)
                {
                    if (tl.State == TouchLocationState.Pressed)
                    {
                        if (playerState == PlayerState.TensingSlingshot && !isTensing && tl.Position.X >= playerStartPosition.X - 20
                            && tl.Position.X <= playerStartPosition.X + 20 && tl.Position.Y >= playerStartPosition.Y - 20
                            && tl.Position.Y <= playerStartPosition.Y + 20)
                        {
                            isTensing = true;
                        }
                        isScreenTouched = true;
                    }
                    else if (tl.State == TouchLocationState.Released)
                    {
                        isScreenTouched = false;
                    }
                    else if (tl.State == TouchLocationState.Moved && playerState == PlayerState.TensingSlingshot && isTensing)
                    {
                        playerPosition = tl.Position;
                        isScreenTouched = true;
                        if (tl.Position.X < 3 || tl.Position.Y > ScreenManager.GraphicsDevice.Viewport.Height - 10)
                        {
                            isScreenTouched = false;

                        }
                    }
                }
            }
            else if (playerState == PlayerState.Flying)
            {
                foreach (TouchLocation tl in input.TouchState)
                {
                    if ((tl.State == TouchLocationState.Pressed || tl.State == TouchLocationState.Moved) && jumpingCount > 10)
                    {
                        isScreenTouched = true;
                    }
                    else if (tl.State == TouchLocationState.Released || jumpingCount <= 10)
                    {
                        isScreenTouched = false;
                    }
                }
            }
            else if (playerState == PlayerState.Sliding)
            {
                foreach (TouchLocation tl in input.TouchState)
                {
                    if ((tl.State == TouchLocationState.Pressed || tl.State == TouchLocationState.Moved))
                    {
                        isJumping = true;
                    }
                    else if (tl.State == TouchLocationState.Released)
                    {
                        isJumping = false;
                    }
                }
            }
        }

        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {
            // This game has a blue background. Why? Because!
            ScreenManager.GraphicsDevice.Clear(ClearOptions.Target,
                                               Color.CornflowerBlue, 0, 0);

            // Our player and enemy are both actually just text strings.
            SpriteBatch spriteBatch = ScreenManager.SpriteBatch;

            spriteBatch.Begin();

            spriteBatch.Draw(mainBackground, Vector2.Zero, Color.White);

            // Draw the moving background
            bgLayer1.Draw(spriteBatch);
            bgLayer2.Draw(spriteBatch);

            // draw the obstacles
            for (int i = 0; i < obstacles.Count; i++)
            {
                obstacles[i].Draw(spriteBatch);
            }

            // draw slingshot parts at the back of player
            slingshot.Draw(spriteBatch, ScreenManager.GraphicsDevice, false);

            // draw the player
            player.Draw(spriteBatch);

            // draw slingshot parts at the front of player
            slingshot.Draw(spriteBatch, ScreenManager.GraphicsDevice, true);

            // draw explosion
            if (explosion.Active)
                explosion.Draw(spriteBatch);

            // draw score
            spriteBatch.DrawString(gameFont, "score:", new Vector2(ScreenManager.GraphicsDevice.Viewport.Width - gameFont.MeasureString("score: 000000").X, ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Y), Color.Black);
            spriteBatch.DrawString(gameFont, "" + score, new Vector2(ScreenManager.GraphicsDevice.Viewport.Width - gameFont.MeasureString(" " + score).X, ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Y), Color.Black);

            spriteBatch.End();

            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0)
                ScreenManager.FadeBackBufferToBlack(1f - TransitionAlpha);
        }


        #endregion

        #region update components

        /// <summary>
        /// Updates the player.
        /// </summary>
        public void UpdatePlayer(GameTime gameTime)
        {
            switch (playerState)
            {
                case PlayerState.TensingSlingshot:
                    if (isTensing)
                    {
                        // animal should be shot away
                        if (!isScreenTouched)
                        {
                            playerState = PlayerState.ShootingAway;
                            player.PlayerAnimal.currentAnimationState = Animal.AnimationState.Starting;
                            isTensing = false;
                            Vector2 shootingVector = playerStartPosition - playerPosition;
                            player.PlayerAnimal.Speed = (float)Math.Sqrt(Math.Pow(shootingVector.X, 2) + Math.Pow(shootingVector.Y, 2)) / 10 * player.PlayerAnimal.Speed;

                            // animal should be shot away up
                            if (shootingVector.Y <= 0)
                            {
                                shootingPlayerVector = new Vector2((-shootingVector.X) / Math.Abs(shootingVector.Y) * player.PlayerAnimal.Speed, player.PlayerAnimal.Speed);
                            }
                            // animal should be shot away down
                            else
                            {
                                shootingPlayerVector = new Vector2((-shootingVector.X) / Math.Abs(shootingVector.Y) * player.PlayerAnimal.Speed, -player.PlayerAnimal.Speed);
                            }
                        }
                    }
                    break;
                case PlayerState.ShootingAway:
                    playerPosition -= shootingPlayerVector;

                    if (playerPosition.X >= ScreenManager.GraphicsDevice.Viewport.Width / 3)
                    {
                        player.PlayerAnimal.currentAnimationState = Animal.AnimationState.Flying;
                        playerState = PlayerState.Flying;
                    }
                    break;
                case PlayerState.Flying:
                    player.PlayerAnimal.Speed -= player.PlayerAnimal.AirResistance / 100;
                    // animal should fall
                    if (isScreenTouched)
                    {
                        playerPosition.Y += player.PlayerAnimal.FallingSpeed;
                        player.PlayerAnimal.currentAnimationState = Animal.AnimationState.Landing;
                    }
                    else
                    {
                        player.PlayerAnimal.currentAnimationState = Animal.AnimationState.Flying;
                    }

                    // collsion has been detected
                    if (collidedWithHelperObstacle)
                    {
                        collisionWithHelperObstacle();
                    }


                    if (player.PlayerAnimal.Speed < 0.0f)
                    {
                        player.PlayerAnimal.Speed = 0.0f;
                    }

                    // player rises
                    if (shootingPlayerVector.Y > 0)
                    {
                        shootingPlayerVector.Y -= player.PlayerAnimal.Gravity / 3.5f;
                    }
                    // player falls
                    else
                    {
                        shootingPlayerVector.Y -= player.PlayerAnimal.Gravity / 100 * gravityMultiplicator;
                        gravityMultiplicator += 0.01f;
                    }
                    playerPosition.Y -= shootingPlayerVector.Y;
                    break;
                case PlayerState.Sliding:
                    if (collidedWithHelperObstacle)
                    {
                        collisionWithHelperObstacle();
                    }
                    player.PlayerAnimal.currentAnimationState = Animal.AnimationState.Sliding;
                    player.PlayerAnimal.Speed -= (player.PlayerAnimal.AirResistance / 100 + player.PlayerAnimal.GroundResistance / 100);
                    if (player.PlayerAnimal.Speed < 0.0f)
                    {
                        player.PlayerAnimal.Speed = 0.0f;
                    }
                    // player is jumping and so should rise
                    if (isJumping)
                    {
                        shootingPlayerVector.Y = (player.PlayerAnimal.Gravity) * 5;
                        gravityMultiplicator = 1.5f;
                        playerState = PlayerState.Flying;
                        player.PlayerAnimal.currentAnimationState = Animal.AnimationState.Flying;
                        playerPosition.Y -= shootingPlayerVector.Y;
                        jumpingCount = 0;
                        isJumping = false;
                    }
                    break;
            }
            // player should be inactive because no more speed
            if (player.PlayerAnimal.Speed == 0.0)
            {
                player.Active = false;
            }
            else
            {
                player.Position = playerPosition;
                player.Update(gameTime);
            }
        }

        /// <summary>
        /// Updates the obstacles.
        /// </summary>
        private void UpdateObstacles(GameTime gameTime)
        {
            if (playerState == PlayerState.Flying || playerState == PlayerState.Sliding)
            {
                AddObstacle();
            }

            for (int i = 0; i < obstacles.Count; i++)
            {
                obstacles[i].MoveSpeed = player.PlayerAnimal.Speed;
                obstacles[i].Update(gameTime);

                if (obstacles[i].Active == false)
                {
                    switch (obstacles[i].Type)
                    {
                        case Obstacle.ObstacleType.Stones:
                        case Obstacle.ObstacleType.Ice:
                            groundObstacles--;
                            break;
                        case Obstacle.ObstacleType.Ballon:
                            flyingObstacles--;
                            break;
                        case Obstacle.ObstacleType.Trampoline:
                            helperObstacles--;
                            break;
                    }
                    obstacles.RemoveAt(i);
                }
            }
        }

        /// <summary>
        /// Updates the slingshot.
        /// </summary>
        private void UpdateSlingshot(GameTime gameTime)
        {
            if (playerState == PlayerState.Flying || playerState == PlayerState.Sliding)
            {
                slingshot.MoveSpeed = player.PlayerAnimal.Speed;
            }
            slingshot.animalPosition = playerPosition;
            slingshot.Update(gameTime);
        }

        /// <summary>
        /// Updates the explosion.
        /// </summary>
        private void UpdateExplosion(GameTime gameTime)
        {
            if (explosion.Active)
            {
                explosion.Update(gameTime);
            }
        }

        /// <summary>
        /// Updates the background.
        /// </summary>
        private void UpdateBackground()
        {
            if (playerState == PlayerState.Flying || playerState == PlayerState.Sliding)
            {
                bgLayer1.Speed = player.PlayerAnimal.Speed / 2;
                bgLayer2.Speed = player.PlayerAnimal.Speed;
                bgLayer1.Update();
                bgLayer2.Update();
            }
        }


        /// <summary>
        /// Updates the score.
        /// </summary>
        private void UpdateScore()
        {

            if (player.Active)
                score -= (int)shootingPlayerVector.X;

        }

        #endregion

        /// <summary>
        /// Checks if the player collided with the fround or an obstacle.
        /// </summary>
        private void checkForCollision()
        {
            Rectangle playerRect = new Rectangle((int)player.Position.X - player.Width / 2,
                (int)player.Position.Y - player.Height / 2, player.Width, player.Height);
            Rectangle testRect;

            if (playerState == PlayerState.Flying)
            {
                // check for ground collision
                testRect = new Rectangle(0, ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Height - groundHeight,
                    ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Width, groundHeight);
                if (playerRect.Intersects(testRect))
                {
                    // touched ground
                    //player.PlayerAnimal.currentAnimationState = Animal.AnimationState.Sliding;
                    playerState = PlayerState.Sliding;
                }
            }

            // check for collisions with obstacles
            for (int i = 0; i < obstacles.Count; i++)
            {
                testRect = new Rectangle((int)obstacles[i].Position.X, (int)obstacles[i].Position.Y, obstacles[i].Width, obstacles[i].Height);
                if (playerRect.Intersects(testRect) && !obstacles[i].AlreadyIntersected)
                {
                    switch (obstacles[i].Type)
                    {
                        case Obstacle.ObstacleType.Ice:
                        case Obstacle.ObstacleType.Stones:
                            player.PlayerAnimal.Speed *= obstacles[i].Friction;
                            break;
                        case Obstacle.ObstacleType.Trampoline:
                            // landed on trampoline
                            if (obstacles[i].Position.X < player.Position.X &&
                                obstacles[i].Position.X + obstacles[i].Width > player.Position.X)
                            {
                                if (!explosion.Active)
                                {
                                    if (isSoundEnabled)
                                    {
                                        jumpSound.Play();
                                    }
                                    obstacles[i].AlreadyIntersected = true;
                                    collidedWithHelperObstacle = true;
                                }
                            }
                            else
                            {
                                startExplosion(i);
                            }
                            break;
                        case Obstacle.ObstacleType.Ballon:
                            if (!explosion.Active)
                            {
                                startExplosion(i);
                            }
                            break;
                    }
                }
            }
        }
        /// <summary>
        /// Adds obstacles if there are not enough in the obstacles list.
        /// </summary>
        private void AddObstacle()
        {
            Obstacle obstacle = new Obstacle(Obstacle.ObstacleType.Stones, obstacleTextures[(int)Obstacle.ObstacleType.Stones]);
            Vector2 position;
            // ground obstacle should be created
            if (groundObstacles <= 2)
            {

                if (random.Next(2) == 1)
                {
                    obstacle = new Obstacle(Obstacle.ObstacleType.Ice, obstacleTextures[(int)Obstacle.ObstacleType.Ice]);
                }
                position = new Vector2(random.Next(ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Width + obstacle.Width / 2, ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Width * 3),
                ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Height - obstacle.Height);
                obstacle.Initialize(position, bgLayer1.Speed);
                if (!areObstaclesColliding(obstacle))
                {
                    // check for collisions of obstacles
                    groundObstacles++;
                    obstacles.Add(obstacle);
                }
            }
            // flying obstacle should be created
            if (flyingObstacles <= 1)
            {

                obstacle = new Obstacle(Obstacle.ObstacleType.Ballon, obstacleTextures[(int)Obstacle.ObstacleType.Ballon]);

                position = new Vector2(random.Next(ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Width + obstacle.Width / 2, ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Width * 3),
                random.Next(obstacle.Height, ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Height - obstacle.Height * 2 - groundHeight));
                obstacle.Initialize(position, bgLayer1.Speed);
                // check for collisions of obstacles
                if (!areObstaclesColliding(obstacle))
                {
                    flyingObstacles++;
                    obstacles.Add(obstacle);
                }
            }
            // helper obstacle should be created
            if (helperObstacles <= 0)
            {

                obstacle = new HelperObstacle(Obstacle.ObstacleType.Trampoline, obstacleTextures[(int)Obstacle.ObstacleType.Trampoline]);
                position = new Vector2(obstacle.Width / 2 + random.Next(ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Width, ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Width * 3),
                ScreenManager.GraphicsDevice.Viewport.TitleSafeArea.Height - obstacle.Height - groundHeight);
                obstacle.Initialize(position, bgLayer1.Speed);
                // check for collisions of obstacles
                if (!areObstaclesColliding(obstacle))
                {
                    helperObstacles++;
                    obstacles.Add(obstacle);
                }
            }

        }

        /// <summary>
        /// Starts playing song as background music.
        /// </summary>
        private void PlayMusic(Song song)
        {
            // Due to the way the MediaPlayer plays music,
            // we have to catch the exception. Music will play when the game is not tethered
            try
            {
                // Play the music
                MediaPlayer.Play(song);

                // Loop the currently playing song
                MediaPlayer.IsRepeating = true;
            }
            catch
            {
            }
        }

        /// <summary>
        /// Starts an explosion at the position of the obstacle with whom the animal collided.
        /// </summary>
        private void startExplosion(int obstacleIndex)
        {
            if (isSoundEnabled)
            {
                explosionSound.Play();
            }

            explosion.Position = obstacles[obstacleIndex].Position;
            explosion.Active = true;
            player.PlayerAnimal.Speed = 0;
            player.Active = false;
            obstacles[obstacleIndex].Active = false;
        }

        /// <summary>
        /// Lets the player get more speed and y-movement.
        /// </summary>
        private void collisionWithHelperObstacle()
        {
            player.PlayerAnimal.Speed += 5;
            if (shootingPlayerVector.Y < -3)
            {
                shootingPlayerVector.Y = shootingPlayerVector.Y * -5.5f;
            }
            else
            {
                shootingPlayerVector.Y = 3 * 5.5f;
            }
            gravityMultiplicator = 1.5f;
            collidedWithHelperObstacle = false;
            jumpingCount = 0;
        }

        /// <summary>
        /// Checks if obstacle is colliding with an already existing obstacle. Returns true when there is a collision, false otherwise.
        /// </summary>
        private bool areObstaclesColliding(Obstacle obstacle)
        {
            Rectangle rect = new Rectangle((int)obstacle.Position.X,
                (int)obstacle.Position.Y, obstacle.Width, obstacle.Height);
            Rectangle testRect;

            // check for collisions with obstacles
            for (int i = 0; i < obstacles.Count; i++)
            {
                testRect = new Rectangle((int)obstacles[i].Position.X, (int)obstacles[i].Position.Y, obstacles[i].Width, obstacles[i].Height);
                if (rect.Intersects(testRect))
                {
                    return true;
                }
            }
            return false;

        }
    }
}
